package cn.iocoder.yudao.boot.redis.core;

import cn.iocoder.yudao.boot.common.util.json.JsonUtils;
import com.fasterxml.jackson.core.type.TypeReference;
import lombok.AllArgsConstructor;
import lombok.Getter;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ZSetOperations;

import java.util.*;
import java.util.concurrent.TimeUnit;

@AllArgsConstructor
public class RedisHelper {

    @Getter
    private RedisTemplate<String, Object> redisTemplate;

    // 字符串存储
    public <T> void set(String key, T value) {
        String v = null;
        if (value instanceof String) {
            v = value.toString();
        } else {
            v = JsonUtils.toJsonString(value);
        }
        redisTemplate.opsForValue().set(key, v);
    }

    // 字符串存储
    public <T> void set(String key, T value, Long timeout, TimeUnit unit) {
        String v = null;
        if (value instanceof String) {
            v = value.toString();
        } else {
            v = JsonUtils.toJsonString(value);
        }
        redisTemplate.opsForValue().set(key, v, timeout, unit);
    }

    // 字符串获取
    public String get(String key) {
        Object obj = redisTemplate.opsForValue().get(key);
        return null == obj ? null : obj.toString();
    }

    public <T> T get(String key, Class<T> clazz) {
        Object obj = redisTemplate.opsForValue().get(key);
        return null == obj ? null : JsonUtils.parseObject(obj.toString(), clazz);
    }

    public <T> T get(String key, TypeReference<T> typeReference) {
        Object obj = redisTemplate.opsForValue().get(key);
        return null == obj ? null : JsonUtils.parseObject(obj.toString(), typeReference);
    }

    // 删除信息
    public Boolean delete(String key) {
        return redisTemplate.delete(key);
    }

    // 删除信息
    public Long delete(Collection<String> keys) {
        return redisTemplate.delete(keys);
    }

    // 列表存储
    public void setList(String key, List<?> values) {
        redisTemplate.opsForList().rightPushAll(key, values);
    }

    // 列表获取
    public <T> List<T> getList(String key, Class<T> clazz) {
        List<Object> values = redisTemplate.opsForList().range(key, 0, -1);
        List<T> result = new ArrayList<>();
        for (Object value : values) {
            try {
                result.add(JsonUtils.parseObject(value.toString(), clazz));
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return result;
    }

    // 列表获取
    public <T> List<T> getList(String key, TypeReference<T> typeReference) {
        List<Object> values = redisTemplate.opsForList().range(key, 0, -1);
        List<T> result = new ArrayList<>();
        for (Object value : values) {
            try {
                result.add(JsonUtils.parseObject(value.toString(), typeReference));
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return result;
    }

    // 集合存储
    public void setSet(String key, Set<?> values) {
        redisTemplate.opsForSet().add(key, values.toArray());
    }

    // 集合获取
    public <T> Set<T> getSet(String key, Class<T> clazz) {
        Set<Object> values = redisTemplate.opsForSet().members(key);
        Set<T> result = new HashSet<>();
        for (Object value : values) {
            try {
                result.add(JsonUtils.parseObject(value.toString(), clazz));
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return result;
    }

    // 集合获取
    public <T> Set<T> getSet(String key, TypeReference<T> typeReference) {
        Set<Object> values = redisTemplate.opsForSet().members(key);
        Set<T> result = new HashSet<>();
        for (Object value : values) {
            try {
                result.add(JsonUtils.parseObject(value.toString(), typeReference));
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return result;
    }

    // 有序集合存储
    public void setZSet(String key, Set<ZSetOperations.TypedTuple<Object>> valueSet) {
        redisTemplate.opsForZSet().add(key, valueSet);
    }

    // 有序集合获取
    public <T> Set<T> getZSet(String key, TypeReference<T> typeReference) {
        Set<Object> values = redisTemplate.opsForZSet().range(key, 0, -1);
        Set<T> result = new HashSet<>();
        for (Object value : values) {
            try {
                result.add(JsonUtils.parseObject(value.toString(), typeReference));
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return result;
    }

    public <T> Set<T> getZSet(String key, Class<T> clazz) {
        Set<Object> values = redisTemplate.opsForZSet().range(key, 0, -1);
        Set<T> result = new HashSet<>();
        for (Object value : values) {
            try {
                result.add(JsonUtils.parseObject(value.toString(), clazz));
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return result;
    }

    // 哈希存储
    public void setMap(String key, Map<String, ?> values) {
        redisTemplate.opsForHash().putAll(key, values);
    }

    // 哈希获取
    public <V> Map<String, V> getMap(String key, Class<V> valueClass) {
        Map<Object, Object> rawMap = redisTemplate.opsForHash().entries(key);
        Map<String, V> result = new HashMap<>();
        for (Map.Entry<Object, Object> entry : rawMap.entrySet()) {
            try {
                String keyValue = (String) entry.getKey();
                V valueValue = JsonUtils.parseObject(entry.getValue().toString(), valueClass);
                result.put(keyValue, valueValue);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return result;
    }

    public <V> Map<String, V> getMap(String key, TypeReference<V> typeReference) {
        Map<Object, Object> rawMap = redisTemplate.opsForHash().entries(key);
        Map<String, V> result = new HashMap<>();
        for (Map.Entry<Object, Object> entry : rawMap.entrySet()) {
            try {
                String keyValue = (String) entry.getKey();
                V valueValue = JsonUtils.parseObject(entry.getValue().toString(), typeReference);
                result.put(keyValue, valueValue);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return result;
    }
}
